/*
  限制输入框只能输入数字、字母、中文等规则

  使用指令：v-input

  修饰符参数说明：
    v-input.num 只能输入数字，默认不传修饰符，会自动限制只能输入数字
    v-input.intp 只能输入正整数
    v-input.num_alp 只能输入数字和字母
    v-input.num_alp_blank 只能输入数字、字母、空格
    v-input.num_alp_sym 只能输入数字和字母、英文符号、空格
    v-input.float 只能输入数字和小数点  v-input.float="{'float':0,'min':0,'max':100000000000000}" 'float':0表示小数位数为0，'min':0，最小值为0，'max':100000000000000，最大值为100000000000000，(默认小数位数为0，最小值为0，最大值为1000000000，你简写为v-input.float)
    v-input.no_emoji 不能输入表情符号

*/
// 只能输入数字
function num(el) {
  el.value = el.value.replace(/\D+/g, '')
}

// 只能输入正整数
function intp(el) {
  const value = el.value.replace(/\D+/g, '') // 去掉非数字字符
  el.value = /^[1-9][0-9]*$/.test(value) ? value : value.replace(/^0+/, '') // 确保为正整数，去掉前导零
}

// 只能输入数字和字母
function num_alp(el) {
  el.value = el.value.replace(/[^A-Za-z0-9]/g, '')
}

// 只能输入数字、字母、空格
function num_alp_blank(el) {
  const regex = /[^a-zA-Z0-9 ]/g
  el.value = el.value.replace(regex, '')
}

// 只能输入数字、字母、英文符号、空格
function num_alp_sym(el) {
  const regex = /[^a-zA-Z0-9`~!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/? ]/g
  el.value = el.value.replace(regex, '')
}

// 只能输入数字和小数点，binding.float表示小数位数. binding.min表示值最小值，binding.max表示最大值
function float(el, binding) {
  const n = binding.float
  let value = el.value
  value = value.replace(/[^\-\d.]/g, '') // 能输入负号，数字和小数点
  value = value.replace(/^\./g, '') // 去掉开头的点
  value = value.replace(/(\d+|\.)-/g, '$1') // 数字和.后面不能接-,不能出现类似11-, 12
  value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.') // 处理多个点的情况
  if (n && Number(n) > 0) {
    const d = new Array(Number(n)).fill('\\d').join('') // 构建正则表达式
    const reg = new RegExp(`^(\\-)*(\\d+)\\.(${d}).*$`, 'ig')
    value = value.replace(reg, '$1$2.$3') // 限制小数位数
  }
  el.value = valueLength(value, binding.min, binding.max, binding.zeroBool)
  //  el.value= value
}

// 限制表情：😀😂❤️🌟🎉🌍🐶☺
function no_emoji(el) {
  const regex =
    /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F1E6}-\u{1F1FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{1F900}-\u{1F9FF}\u{263A}]+/gu
  el.value = el.value.replace(regex, '')
}

// 这里扩展限制的类型
const map = { num, intp, num_alp, num_alp_blank, num_alp_sym, float, no_emoji }

// 限制值的长度 min表示值最小值，max表示最大值
function valueLength(value, min = 0, max = 1000000000,zeroBool = true) {
  // console.log('value------',value)
  if (value) {
    // console.log('value有值')
    if (value < 0) {
      // console.log('value小于0----value < 0')
      if (min >= 0) {
        // console.log('min大于等于0----min >= 0')
        if (zeroBool) {
          value = 0
        } else {
          value = null
        }
      }
      if (min < 0 && value <= min) {
        // console.log('min小于等于0 && value值小于等于min----min < 0 && value <= min')
        value = min
      }
    } else {
      // console.log('value大于0----')
      if (value <= min) {
        // console.log('value小于等于min----')
        if (zeroBool) {
          value = min
        } else {
          value = null
        }
      }
    }
    if (value >= max) {
      // console.log('value大于等于max----')
      value = max
    }
  } else {
    if (zeroBool) {
      value = min
    } else {
      value = null
    }
  }
  return value
}
export default {
  bind(el, binding, vnode) {
    el = el.querySelector('.el-input__inner') || el.querySelector('.el-textarea__inner') || el
    let lock = false // 标记是否需要锁定输入框
    let isHandling = false // 标记是否正在处理
    let lastValue = null
    // input事件处理函数
    const handler = () => {
      if (lock) return // 如果当前为锁定状态，则不进行处理
      if (isHandling) return // 如果已经在处理中，则不进行处理
      if (el.value === lastValue) return // 输入内容没有变化，则不进行处理
      isHandling = true // 设置标记为处理中
      const modifiers = Object.keys(binding.modifiers)
      const newModifier = modifiers[0] || 'num'
      map[newModifier](el, binding.value || 2)
      lastValue = el.value // 记录当前输入框的值
      Promise.resolve().then(() => {
        // 异步处理，场景：火狐浏览器中，需要在最后派发input事件
        el.dispatchEvent(new Event('input'))
      })
      isHandling = false // 处理完毕后设置标记为非处理状态
    }
    el.addEventListener('input', handler)
    // compositionstart和compositionend事件解决的bug场景：限制只能输入数字的输入框，先输入数字，再切换为中文输入法，输入字母时，会将原来的数字删掉
    el.addEventListener('compositionstart', () => {
      lock = true
    })
    el.addEventListener('compositionend', () => {
      lock = false
      el.dispatchEvent(new Event('input'))
    })
    // 当指令与元素解绑时，移除事件监听器
    vnode.context.$once('hook:destroyed', () => {
      el.removeEventListener('input', handler)
    })
  }
}

